import React, { CSSProperties, useEffect, useImperativeHandle, useRef, useState } from 'react';
// import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import * as monaco from 'monaco-editor';
import { EditorLanguage } from 'monaco-editor/esm/metadata';
import { ToolBarProps, ToolBar } from '@/components/MonacoEditor/ToolBar';

declare type ApiType = monaco.editor.IStandaloneCodeEditor;
declare type ThemeType = 'vs' | 'vs-dark' | 'hc-black';

declare type EditorConstructionOptions = Omit<
  monaco.editor.IStandaloneEditorConstructionOptions,
  'language' | 'theme'
> & {
  language?: EditorLanguage;
  theme?: ThemeType;
};

declare type MonacoEditorRefType = {
  getMonacoEditorInstance: () => ApiType;
};

interface MonacoEditorProps {
  height: CSSProperties['height'];
  options?: EditorConstructionOptions;
  toolbar?: false | Omit<ToolBarProps, 'editor' | 'options'>;
}

const MonacoEditor = React.forwardRef<MonacoEditorRefType, MonacoEditorProps>(
  (props, ref) => {
    const { height, options, toolbar = {} } = props;

    const root = useRef<HTMLDivElement>(null);
    const [ editor, setEditor ] = useState<ApiType>();

    useImperativeHandle(
      ref,
      () => {
        return {
          getMonacoEditorInstance: () => editor as any,
        };
      },
      [ editor ],
    );

    useEffect(() => {
      if (root.current) {
        const api: ApiType = monaco.editor.create(root.current, {
          language: 'javascript',
          theme: 'vs',
          ... options,
          automaticLayout: true,
        });

        setEditor(api);

        return () => api.dispose();
      }
    }, [ root ]);

    return (
      <div style={ { display: 'flex', flexDirection: 'column', gap: 4 } }>
        { toolbar === false ? null : (
          <ToolBar { ... toolbar } editor={ editor } options={ options } />
        ) }
        <div id="root" ref={ root } style={ { height } }></div>
      </div>
    );
  },
);

export default MonacoEditor;
export { MonacoEditorRefType, MonacoEditorProps, ApiType, ThemeType, EditorConstructionOptions };
